package net.melon.agency.pojo;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

import javax.persistence.Transient;

import net.esj.auth.pojo.CoreAuthFunc;
import net.esj.basic.pojo.AbstractPojo;
import net.esj.basic.pojo.op.Administrator;
import net.esj.basic.pojo.op.Operation;
import net.esj.basic.pojo.op.OperationSet;
import net.esj.basic.pojo.op.Operator;

import org.apache.commons.lang.StringUtils;


public class AgencyUser extends AbstractPojo<String> implements Operator ,Administrator{

	/**
	 * 
	 */
	private static final long serialVersionUID = -6422227637727747369L;
	

	public static final String MOBJECT_TYPE = "AGENCY_USER";
	
	public static enum AgencyUserState{
		
		NORMAL(0),
		STOP(1);
		
		private int state;

		private AgencyUserState(int state) {
			this.state = state;
		}

		public int getState() {
			return state;
		}
		
		public static AgencyUserState valueOf(int state){
			for(AgencyUserState os : values()){
				if(os.getState()== state){
					return os;
				}
			}
			return null;
		}
		
	}
	
	private String id;
	private Agency agency;
	private String name;
	private String password;
	private String subName;
	private String address;
	private String mobile;
	private String linkPhone;
	private Date gmtCreate;
	private Date gmtModify;
	private Date lastLoginTime;
	private String lastLoginIp;
	
	private int state;
	
	private boolean isSuper;
	
	private String agencyUseId;
	

	public String getAgencyUseId() {
		return agencyUseId;
	}

	public void setAgencyUseId(String agencyUseId) {
		this.agencyUseId = agencyUseId;
	}

	private Set<AgencyGroup> groups = new HashSet<AgencyGroup>(0);
	

	private Set<CoreAuthFunc> funcs = new AgencyFuncHashSet<CoreAuthFunc>(0);
	
	private List<CoreAuthFunc> allowedFunctions = Collections.EMPTY_LIST; 
	
	private List<CoreAuthFunc> allowedTree = Collections.EMPTY_LIST;
	
	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public Agency getAgency() {
		return agency;
	}

	public void setAgency(Agency agency) {
		this.agency = agency;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getSubName() {
		return subName;
	}

	public void setSubName(String subName) {
		this.subName = subName;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public String getMobile() {
		return mobile;
	}

	public void setMobile(String mobile) {
		this.mobile = mobile;
	}

	public String getLinkPhone() {
		return linkPhone;
	}

	public void setLinkPhone(String linkPhone) {
		this.linkPhone = linkPhone;
	}

	public Date getGmtCreate() {
		return gmtCreate;
	}

	public void setGmtCreate(Date gmtCreate) {
		this.gmtCreate = gmtCreate;
	}

	public Date getGmtModify() {
		return gmtModify;
	}

	public void setGmtModify(Date gmtModify) {
		this.gmtModify = gmtModify;
	}

	public Date getLastLoginTime() {
		return lastLoginTime;
	}

	public void setLastLoginTime(Date lastLoginTime) {
		this.lastLoginTime = lastLoginTime;
	}

	public String getLastLoginIp() {
		return lastLoginIp;
	}

	public void setLastLoginIp(String lastLoginIp) {
		this.lastLoginIp = lastLoginIp;
	}

	public int getState() {
		return state;
	}

	public void setState(int state) {
		this.state = state;
	}

	public Set<AgencyGroup> getGroups() {
		return groups;
	}

	public void setGroups(Set<AgencyGroup> groups) {
		for(AgencyGroup ag : groups){
			if(!hasGroup(ag.getId())){
				this.groups.add(ag);
			}
		}
	}

	public Set<CoreAuthFunc> getFuncs() {
		return funcs;
	}
	
	

	public void setFuncs(Set<CoreAuthFunc> funcs) {
		this.funcs = funcs;
	}

	public void setSuper(boolean isSuper) {
		this.isSuper = isSuper;
	}

	public void setAllowedFunctions(List<CoreAuthFunc> allowedFunctions) {
		this.allowedFunctions = allowedFunctions;
	}
	
	public List<CoreAuthFunc> getAllowedTree() {
		if(allowedTree == Collections.EMPTY_LIST){
			allowedTree = new ArrayList<CoreAuthFunc>();
			for(CoreAuthFunc func : allowedFunctions()){
				if(func.getParent()==null){//根目录
					allowedTree.add(func);
					setChild(func, allowedFunctions());
				}
			}
		}
		return allowedTree;
	}

	private void setChild(CoreAuthFunc parent ,List<CoreAuthFunc> list){
		for(CoreAuthFunc bm : list){
			if(bm.getParent()!=null &&  StringUtils.equals(bm.getParent().getId(), parent.getId())){
				parent.getChildren().add(bm);
				setChild(bm, list);
			}
		}
	}
	@Transient
	public boolean isAllowed(String uri, Map requestParams) {
		for(CoreAuthFunc func: allowedFunctions()){
			if(Pattern.matches(func.getAnalyzedUrl(), uri)
					&& CoreAuthFunc.checkParams(func.getParams(), requestParams)){
				return true;
			}
			for(Map.Entry<String, Map<String,String[]>> entry: func.getRights().entrySet()){
				if(Pattern.matches(entry.getKey(), uri)
						&& CoreAuthFunc.checkParams(entry.getValue(), requestParams)){
					return true;
				}
			}
		}
		return false;
	}

	@Override
	@Transient
	public String getMType() {
		return MOBJECT_TYPE;
	}

	@Override
	@Transient
	public boolean isSuper() {
		return this.isSuper;
	}

	@Override
	public Collection<CoreAuthFunc> authFunctions() {
		return allowedFunctions();
	}

	@Override
	public OperationSet findOperations(String uri, Map requestParams) {
		OperationSet set = new OperationSet();
		for(CoreAuthFunc func: allowedFunctions()){
			if(Pattern.matches(func.getAnalyzedUrl(), uri)
					&& CoreAuthFunc.checkParams(func.getParams(), requestParams)){
				if(func.getIsOper()){
					Operation op = new Operation();
					op.setBody(func.getDefine());
					op.setIcon(func.getIcon());
					op.setTarget(func.getScope());
					op.setTitle(func.getName());
					op.setSort(func.getSort());
					op.setCheck(func.getDefineCheck());
					set.push(op);
				}
			}
		}
		return set;
	}

	public List<CoreAuthFunc> allowedFunctions() {
		if(allowedFunctions == Collections.EMPTY_LIST){
			Set<CoreAuthFunc> tempFuncs = new HashSet<CoreAuthFunc>();//必须先要用set过滤重复项
			for(AgencyGroup group: getGroups()){
				tempFuncs.addAll(group.getFunctions());
			}
			for(CoreAuthFunc f:getFuncs()){
				appendAllowedFuncs(tempFuncs, f);
			}
			//tempFuncs.addAll(getFuncs());
			allowedFunctions = new ArrayList<CoreAuthFunc>(tempFuncs);
			Collections.sort(allowedFunctions, new Comparator<CoreAuthFunc>() {

				@Override
				public int compare(CoreAuthFunc o1, CoreAuthFunc o2) {
					return o1.getSort() - o2.getSort();
				}
			});
		}
		return allowedFunctions;
	}
	
	private void appendAllowedFuncs(Set<CoreAuthFunc> set,CoreAuthFunc func){
		set.add(func);
		for(CoreAuthFunc f : func.getChildren()){
			appendAllowedFuncs(set, f);
		}
	}
	
	public boolean hasGroup(String id){
		for(AgencyGroup group:groups){
			if(StringUtils.equals(id, group.getId())){
				return true;
			}
		}
		return false;
	}
	
	private static final class AgencyFuncHashSet<E  extends CoreAuthFunc> extends HashSet<CoreAuthFunc>{

		/**
		 * 
		 */
		private static final long serialVersionUID = 2678244355533672459L;
		
		public AgencyFuncHashSet() {
			super();
		}

		public AgencyFuncHashSet(Collection<? extends CoreAuthFunc> c) {
			super(c);
		}

		public AgencyFuncHashSet(int initialCapacity, float loadFactor) {
			super(initialCapacity, loadFactor);
		}

		public AgencyFuncHashSet(int initialCapacity) {
			super(initialCapacity);
		}

		@Override
		public boolean add(CoreAuthFunc arg0) {
			for(CoreAuthFunc f : this){
				if(StringUtils.equals(f.getId(), arg0.getId())){
					return false;
				}
			}
			return super.add(arg0);
		}

	
		
	}
	
}


